<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <div id="app">
    <todo-header></todo-header>

    <todo-input @add="addTodoItem"></todo-input>

    <todo-list :todos="todos"></todo-list>
  </div>

  <script src="./libs/vue.js"></script>
  <script>
    // 定义一个全局变量，用于保存 event-bus 中使用到的对象
    const bus = new Vue()

    // 定义 TodoHeader 组件
    Vue.component('TodoHeader', {
      template: `
        <div>
          <slot name="title">
            <h2>待办事项列表</h2>
          </slot>
          <slot name="subtitle">
            <h3>今日事，今日毕！</h3>
          </slot>
        </div>
      `
    })

    // 定义 TodoInput 组件
    Vue.component('TodoInput', {
      template: `
        <div>
          <input
            type="text"
            placeholder="请输入新待办事项"
            v-model.trim="inputValue"
            class="input"
            ref="inputRef"
            @keydown.enter="handleAdd"
          >
          <button @click="handleAdd">添加</button>
        </div>
      `,
      data() {
        return {
          inputValue: ''
        }
      },
      methods: {
        handleAdd() {
          // 输入框自动获得焦点
          this.$refs.inputRef.focus()
          // 如果输入内容为空，不添加
          if (this.inputValue.length === 0) {
            return
          }
          // 触发父组件中定义的事件，向父组件传递数据
          this.$emit('add', this.inputValue)
          // 清空文本框
          this.inputValue = ''
        }
      },
    })

    // 定义 TodoList 组件
    Vue.component('TodoList', {
      // 可以使用 v-bind="todo" 将 todo 对象中所有属性展开后传递给子组件
      template: `
        <div>
          <h3>所有待办事项：</h3>
          <ul v-if="total">
            <todo-item
              v-for="todo in todos"
              :id="todo.id"
              :title="todo.title"
              :completed="todo.completed"
              :key="todo.id"
            ></todo-item>
          </ul>
          <div v-else>待办事项为空，请添加新待办事项！</div>
          <div>共计{{ total }}项，已完成{{ completed }}项，未完成{{ uncompleted }}项</div>
          <a href="https://www.baidu.com" @click.prevent>删除{{ completed }}项已完成事项</a>
        </div>
      `,
      props: { // 属性，从父组件中接收传递的数据
        todos: {
          type: Array,
          required: true
        }
      },
      computed: { // 计算属性
        total() {
          return this.todos.length
        },
        completed() {
          return this.todos.filter(todo => todo.completed).length
        },
        uncompleted() {
          return this.total - this.completed
        }
      },
      components: { // 局部组件注册
        TodoItem: { // TodoItem 组件
          template: `
            <li>
              <input type="checkbox" @change="handleToggle">
              {{ id }} - {{ title }} - {{ completed ? '已' : '未' }}完成 - 
              <button @click="handleToggle">修改完成状态</button>
              <button @click="handleRemove">删除</button>
            </li>
          `,
          props: {
            id: {
              type: Number
            },
            title: {
              type: String
            },
            completed: {
              type: Boolean,
              default: false
            }
          },
          methods: {
            handleToggle() {
              bus.$emit('toggle', this.id)
            },
            handleRemove() {
              bus.$emit('remove', this.id)
            }
          }
        }
      }
    })

    // 初始化几个待办事项
    const initTodos = Array(6).fill(null).map((v, i) => ({
      id: i + 1,
      title: '待办事项' + (i + 1),
      completed: false
    }))

    // 用于保存全局 id
    let index = initTodos.length

    const vm = new Vue({
      el: '#app',
      data() {
        return {
          todos: initTodos
        }
      },
      // 在实例创建后会被自动调用到
      created() {
        // 注册事件监听，接收待修改/待删除待办事项的数据
        bus.$on('toggle', this.toggleTodoItem)
        bus.$on('remove', this.removeTodoItem)
      },
      methods: {
        /**
         * 添加待办事项
         */
        addTodoItem(title) {
          this.todos.push({
            id: ++index,
            title,
            completed: false,
          })
        },
        /**
         * 删除待办事项
         */
        removeTodoItem(id) {
          this.todos = this.todos.filter(todo => todo.id !== id)
        },
        /**
         * 修改待办事项的状态
         */
        toggleTodoItem(id) {
          // 从数组中找出 id 对应的项
          const todo = this.todos.find(todo => todo.id === id)
          // 修改完成状态
          todo.completed = !todo.completed
        },
      }
    })
  </script>
</body>
</html>